﻿////////////////////////////////////////////////////////////////////////////////////
//
//   QDTDToXML.cpp
//   Description: main UI
//   Revision History: 03/25/2020 created by Zhang Hong
//
////////////////////////////////////////////////////////////////////////////////////

#ifndef __GNUC__
#pragma execution_character_set("utf-8")
#endif

#include "QDTDToXML.h"
#include "ParseDTD.h"
#include "CopyFileReplace.h"

#include <QFileDialog>
#include <QMessageBox>
#include <QTextStream>
#include <QSettings>
#include <QUuid>


#if defined(_WIN64) || defined(__GNUC__)
const QString g_Version = QStringLiteral("DTDToXML(v1.0.20200311-64)");
#else
const QString g_Version = QStringLiteral("DTDToXML(v1.0.20200311-32)");
#endif

using namespace std;

//取得文件名，包括扩展名
QString GetFileName(const QString &fullPath)
{
	QFileInfo fileInfo;
	fileInfo = QFileInfo(fullPath);
	return fileInfo.fileName();
}

//取得文件名，不包括扩展名
QString GetBaseName(const QString &fullPath)
{
	QFileInfo fileInfo;
	fileInfo = QFileInfo(fullPath);
	return fileInfo.baseName();
}

//取得目录名，末尾为“/”
QString GetDir(const QString &fullPath)
{
	QFileInfo fileInfo;
	fileInfo = QFileInfo(fullPath);
	QString dir = fileInfo.absolutePath();
	return dir + "/";
}

//判断目录是否存在，不存在则创建，支持多级目录
bool isDirExist(const QString &fullPath)
{
	QDir dir(fullPath);
	if (dir.exists())
	{
		return true;
	}
	else
	{
		bool ok = dir.mkpath(fullPath);//创建多级目录
		return ok;
	}
}

QDTDToXML::QDTDToXML(QWidget *parent)
	: QMainWindow(parent)
	, m_sDTDFileName("")
	, m_sOldContent("")
{
	ui.setupUi(this);

	m_sIniFile = QCoreApplication::applicationDirPath() + "/DTDToXML.ini";

}

void QDTDToXML::on_actionOpen_triggered()
{
	//打开DTD
	QSettings setting(m_sIniFile, QSettings::IniFormat);
	QString s1 = setting.value("Data/LastFile", "").toString();

	m_sDTDFileName = QFileDialog::getOpenFileName(this, "打开文件", s1, tr("DTD文件 (*.dtd *.DTD)"));
	if (m_sDTDFileName.isEmpty())
	{
		on_actionNew_triggered();
		updateTitle();
		return;
	}

	QFile file(m_sDTDFileName);
	if (!file.open(QFile::ReadOnly | QFile::Text))
		return;

	m_sOldContent = file.readAll();
	ui.textEdit->setPlainText(m_sOldContent);

	file.close();

	setting.setValue("Data/LastFile", m_sDTDFileName);

	updateTitle();
}

void QDTDToXML::on_actionSave_triggered()
{
	if (m_sOldContent.isEmpty())
	{
		on_actionSaveAs_triggered();
		return;
	}

	QFile file(m_sDTDFileName);
	if (!file.open(QFile::WriteOnly | QFile::Text))
		return;

	m_sOldContent = ui.textEdit->toPlainText();
	file.write(m_sOldContent.toStdString().c_str());

	file.close();
}

void QDTDToXML::on_actionSaveAs_triggered()
{
	QString sFile = QFileDialog::getSaveFileName(this, tr("另存为"), m_sDTDFileName, tr("DTD文件 (*.dtd *.DTD)"));
	if (sFile.isEmpty()) return;
	m_sDTDFileName = sFile;

	QSettings setting(m_sIniFile, QSettings::IniFormat);
	setting.setValue("Data/LastFile", m_sDTDFileName);

	on_actionSave_triggered();
	updateTitle();
}

void QDTDToXML::on_actionNew_triggered()
{
	if (!verifySave()) return;

	m_sDTDFileName = "";
	ui.textEdit->setPlainText("");
	updateTitle();
}

void QDTDToXML::on_actionClose_triggered()
{
	on_actionNew_triggered();
}

bool QDTDToXML::verifySave()
{
	if (m_sOldContent != ui.textEdit->toPlainText())
	{
		int r = QMessageBox::question(this, tr("提问"), tr("是否保存已修改的文件？"),
			QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel, QMessageBox::Save);
		if (QMessageBox::Cancel == r) return false;
		if (QMessageBox::Save == r)
			on_actionSave_triggered();
	}
	return true;
}

void QDTDToXML::updateTitle()
{
	if (m_sDTDFileName == "")
		setWindowTitle(g_Version);
	else
		setWindowTitle(g_Version + " -- " + m_sDTDFileName);
}

void QDTDToXML::on_actionToCPP_triggered()
{
	if (!verifySave()) return;

	QSettings *setting = new QSettings(m_sIniFile, QSettings::IniFormat);
	QString s1 = setting->value("Data/LastPrjDir", "").toString();

	m_sPrjDir = QFileDialog::getExistingDirectory(this, tr("输出目录"), s1);
	if (m_sPrjDir.isEmpty())
		return;
	m_sPrjDir.replace("\\", "/");
	if (m_sPrjDir.right(1) != "/") m_sPrjDir += "/";
	setting->setValue("Data/LastPrjDir", m_sPrjDir);
	delete setting;

	//读入XML结构
	std::list<CElement> elmList;
	int ret = ParseDTD(m_sOldContent, elmList, ui.treeWidget);
	if (ret != 0) return;

	//取得文件名，不含路径和扩展名
	QString baseName = GetBaseName(m_sDTDFileName);

	PrjMacro prjMacro;
	
	prjMacro.$TempleteDir = QCoreApplication::applicationDirPath() + "/../../../Template/";
	prjMacro.$Project = baseName;
	prjMacro.$PROJECT = baseName.toUpper();
	prjMacro.$project = baseName.toLower();
	prjMacro.$QT32 = "msvc2013";
	prjMacro.$QT64 = "msvc2013_64";
	prjMacro.$UUID = QUuid::createUuid().toString();

	CElement *topElm = TopElement(elmList);
	if (!topElm) return;
	prjMacro.$TopNode = topElm->name;

	//基类
	QString baseFileList[] = {
		"QBaseXML/QBaseXML.h",
		"QBaseXML/QBaseXML.cpp",
		"QBaseXML/QBaseXML.filters",
		"QBaseXML/QBaseXML.pri",
		"QBaseXML/QBaseXML.pro",
		"QBaseXML/QBaseXML.vcxproj",
		"QBaseXML/qbasexml_global.h",
	};
	for (auto &file : baseFileList)
	{
		QString desFile = m_sPrjDir + file;
		isDirExist(GetDir(desFile));
		QFile::copy(prjMacro.$TempleteDir + file, desFile);	//创建目录，直接复制文件
	}

	//顶层结点
	QString prjFileList[] = {
		"{$Project}XML/{$Project}XML.h",
		"{$Project}XML/{$Project}XML.cpp",
		"{$Project}XML/{$Project}XML.filters",
		"{$Project}XML/{$Project}XML.pri",
		"{$Project}XML/{$Project}XML.pro",
		"{$Project}XML/{$Project}XML.vcxproj",
		"{$Project}XML/{$project}xml_global.h",
	};

	//子结点
	QString nodeHeader = "{$Project}XML/{$Node}.h";
	QString nodeSource = "{$Project}XML/{$Node}.cpp";

	for (auto &file : prjFileList)
	{
		QString desFile = m_sPrjDir + ReplaceFile(file, prjMacro.$Project, prjMacro.$project, prjMacro.$TopNode);
		isDirExist(GetDir(desFile));
		CopyFileReplace(prjMacro.$TempleteDir + file, desFile, prjMacro, elmList, *topElm);
	}

	for (auto &elm : elmList)
	{
		QString desHeader = m_sPrjDir + ReplaceFile(nodeHeader, prjMacro.$Project, prjMacro.$project, elm.name);
		CopyFileReplace(prjMacro.$TempleteDir + nodeHeader, desHeader, prjMacro, elmList, elm);
		
		QString desSource = m_sPrjDir + ReplaceFile(nodeSource, prjMacro.$Project, prjMacro.$project, elm.name);
		CopyFileReplace(prjMacro.$TempleteDir + nodeSource, desSource, prjMacro, elmList, elm);
	}

	//测试项目
	QString testFileList[] = {
		"test_{$Project}XML.sln",
		"test_{$Project}XML/main.cpp",
		"test_{$Project}XML/test_{$Project}XML.h",
		"test_{$Project}XML/test_{$Project}XML.cpp",
		"test_{$Project}XML/test_{$Project}XML.qrc",
		"test_{$Project}XML/test_{$Project}XML.ui",
		"test_{$Project}XML/test_{$Project}XML.vcxproj",
		"test_{$Project}XML/test_{$Project}XML.filters",
		"test_{$Project}XML/test_{$Project}XML.pri",
		"test_{$Project}XML/test_{$Project}XML.pro",
	};
	for (auto &file : testFileList)
	{
		QString desFile = m_sPrjDir + ReplaceFile(file, prjMacro.$Project, prjMacro.$project, prjMacro.$TopNode);
		isDirExist(GetDir(desFile));
		CopyFileReplace(prjMacro.$TempleteDir + file, desFile, prjMacro, elmList, *topElm);
	}



	QMessageBox::information(this, tr("提示"), tr("程序生成完毕!"));
}
